#include "SimpleByteBuffer.h"
#include <string.h>
#include <stdlib.h>

SimpleByteBuffer::SimpleByteBuffer():
    m_MaxSize(0),
    m_Offset(0),
    m_CurrOffset(0),
    m_Buffer(nullptr)
{
}

SimpleByteBuffer::~SimpleByteBuffer()
{
    if (m_Buffer != nullptr)
        free(m_Buffer);
}

//写入数据到缓冲区
bool SimpleByteBuffer::Put(const unsigned char * buf, const unsigned int size){
    //整理缓冲区 保证数据有足够空间可以写入
    TidyBuf(size);
    memcpy(&m_Buffer[m_CurrOffset], buf, size);
    MoveWOffset(size);
    return true;
}

//缓冲区可读取数据起始地址
const unsigned char * SimpleByteBuffer::RBuf() {
    return &m_Buffer[m_Offset];
}

//缓冲区可写入起始地址
char * SimpleByteBuffer::WBuf() {
    return (char *)&m_Buffer[m_CurrOffset];
}

//检查缓冲区中是否有有效数据
bool SimpleByteBuffer::CanRead() const {
    return m_Offset < m_CurrOffset;
}

//获取缓冲区中可读数据的大小
unsigned int SimpleByteBuffer::CanReadSize() const {
    return m_CurrOffset - m_Offset;
}

//偏移读取地址
void SimpleByteBuffer::MoveROffset(const unsigned int size) {
    m_Offset += size;
}

//获取缓冲区可写入数据大小
unsigned int SimpleByteBuffer::CanWriteSize() const {
    return m_MaxSize - m_CurrOffset;
}

//偏移写入地址
void SimpleByteBuffer::MoveWOffset(const unsigned int size) {
    m_CurrOffset += size;
}

//重置缓冲区数据
void SimpleByteBuffer::Reset() {
    m_Offset = 0;
    m_CurrOffset = 0;
}

//返回缓冲区最大大小
unsigned int SimpleByteBuffer::MaxSize() const {
    return m_MaxSize;
}

//整理缓冲区 清除废弃数据 解放缓冲区 不足则 扩充缓冲区大小
void SimpleByteBuffer::TidyBuf(const unsigned int size) {
    //如果空间足够 则不扩充
    if (CanWriteSize() > size)
        return;

    //如果有已读取数据可重用的空间，则清除数据解放空间
    if (m_Offset > 0) {
        //如果缓冲区中数据未全部读取， 则剩余数据需要保留 否则全部清除
        unsigned int data_len = 0;
        if (m_CurrOffset > m_Offset) {
            //可读取数据
            data_len = m_CurrOffset - m_Offset;
            //从缓存可读数据起始地址起 将所有可读数据移动到缓冲区起始地址，会前面覆盖已读取的垃圾数据
            memcpy(m_Buffer, &m_Buffer[m_CurrOffset], data_len);
        }
        m_Offset = 0;
        m_CurrOffset = data_len;
    }

    //如果已读取清理数据后 空间足够则不扩充
    if (CanWriteSize() > size)
        return;

    //扩充一个块大小
    m_MaxSize += BLOCKSIZE;
    m_Buffer = reinterpret_cast<unsigned char *>(realloc(m_Buffer, m_MaxSize));
}
